/*
 * Copyright (c) 2025 Huawei Device, Inc. Ltd. and <马弓手>.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "cJSON.h"
#include "ConnPool.h"
#include "FileCache.h"
#include "FileTransfer.h"
#include "file/FileUtils.h"
#include "multimedia/image_framework/image_packer_mdk.h"
#include <cstddef>
#include <multimedia/image_framework/image_source_mdk.h>
#include <multimedia/image_framework/image_pixel_map_mdk.h>
#include <filemanagement/file_uri/oh_file_uri.h>
#include <multimedia/image_framework/image_mdk_common.h>
#include <sys/stat.h>
REGISTER_PLUGIN_CLASS(FileTransfer)

const string FileTransfer::LINE_START = "--";
const string FileTransfer::LINE_END = "\r\n";
const string FileTransfer::BOUNDARY = "+++++";

bool FileTransfer::execute(const string&  actionAsString, cJSON* args, CallbackContext cbc)
{
    if(actionAsString == "upload" || actionAsString == "download") {
        HttpRequest* pHttpRequest = new HttpRequest();
        cJSON* pJson = cJSON_Duplicate(args, 1);
        pHttpRequest->SetFileTransfer(this, actionAsString, pJson, cbc);
        pHttpRequest->Start(nullptr);
    } else if(actionAsString == "abort") {
        string strObjectId = "";
        if(cJSON_GetArraySize(args) > 0) {
            if(cJSON_GetArrayItem(args, 0)->type == cJSON_Number) {
                char szBuf[64];
                int nId = cJSON_GetArrayItem(args, 0)->valueint;
                sprintf(szBuf, "%d", nId);
                strObjectId = szBuf;
            }
            if(cJSON_GetArrayItem(args, 0)->type == cJSON_String) {
                strObjectId = cJSON_GetArrayItem(args, 0)->valuestring;
            }
            if(!strObjectId.empty()) {
                setHttpRequestThreadAbort(strObjectId);
            }
            
        }
        cbc.success();
    }
    return true;
}


void FileTransfer::setHttpRequestThread(const HttpRequest* pRequest)
{
    //添加新的任务之前，清除之前已经完成的任务
    std::lock_guard<std::mutex> guard(m_mutex);
    for(auto it = m_vecHttpRequestThread.begin(); it != m_vecHttpRequestThread.end(); ) {
        HttpRequest* pTmp = *it;
        if(!pTmp->IsRunning()) {
            delete pTmp;
            it = m_vecHttpRequestThread.erase(it);
        } else {
            ++it;
        }
    }
    m_vecHttpRequestThread.push_back((HttpRequest*)pRequest);
}

bool FileTransfer::setHttpRequestThreadAbort(const string strReqId)
{
    std::lock_guard<std::mutex> guard(m_mutex);
    for(int i=0; i<m_vecHttpRequestThread.size(); i++) {
        HttpRequest* pRequest = (HttpRequest*)m_vecHttpRequestThread[i];
        if(pRequest->getReqId() == strReqId) {
            pRequest->setAbort();
            return true;
        }
    }
    return false;
}

/*
POST /upload HTTP/1.1
Host: example.com
Content-Type: multipart/form-data; boundary=WebKitFormBoundary7MA4YWxkTrZu0gW
Content-Length: 1234

--WebKitFormBoundary7MA4YWxkTrZu0gW
Content-Disposition: form-data; name="file”

数据

--WebKitFormBoundary7MA4YWxkTrZu0gW
Content-Disposition: form-data; name="file”

数据

--WebKitFormBoundary7MA4YWxkTrZu0gW
Content-Disposition: form-data; name="file”

数据

--WebKitFormBoundary7MA4YWxkTrZu0gW
Content-Disposition: form-data; name="file"; filename="example.jpg"
Content-Type: image/jpeg

[文件的二进制数据]
--WebKitFormBoundary7MA4YWxkTrZu0gW--
*/
void FileTransfer::upload(const string& strSource, const string& strTarget, cJSON* args, void* pBuf, const int nLength,  CallbackContext cbc, HttpRequest* pRequest)
{
    string strFileKey = getArgument(args, 2, "file");
    string strFileName = getArgument(args, 3, "image.jpg");
    string strMimeType = getArgument(args, 4, "image/jpg");
    cJSON* params = cJSON_GetArrayItem(args, 5);

    bool chunkedMode = true;
    if(cJSON_GetArrayItem(args, 7) != NULL && cJSON_GetArrayItem(args, 7)->type == cJSON_False) {
        chunkedMode = false;
    }
    cJSON* headers = NULL;
    if(cJSON_GetArrayItem(args, 8) == NULL) {
        headers = cJSON_GetObjectItem(params, "headers");
    } else {
        headers = cJSON_GetArrayItem(args, 8);
    }
    
    string objectId = getArgument(args, 9, ""); 
    string httpMethod = getArgument(args, 10, "POST");
    
    pRequest->setReqId(objectId);
    setHttpRequestThread(pRequest);
    
    struct stat statBuf;
    int res = -1;
	if(stat(strSource.c_str(), &statBuf) != 0) {//获取linux操作系统下文件的属性
        return;
    }
    
    if(!S_ISREG(statBuf.st_mode)) {
        return;
    } 
    
    int nFileSize = statBuf.st_size;
    
    //1，解析url
    string urlPath = strTarget;
    string requestAddress = "";
    urlPath = urlPath.erase(0, urlPath.find_first_not_of(" "));
    urlPath = urlPath.erase(urlPath.find_last_not_of(" ") + 1);
    if(urlPath.find("//") != string::npos) {
        requestAddress = urlPath.substr(urlPath.find("//")+2);
    }
    
    //2,解析http/https协议类型
    int nPort = 0;
    bool isHttps = false;
    if(urlPath.find("https") == 0) {
        isHttps = true;
        nPort = 443;
    } else if(urlPath.find("http") == 0) {
        isHttps = false;
        nPort = 80;
    } else {
        return;
    }
    
    //3解析域名修改请求地址
    string strDomainAndPort;
    string strDomain;
    if(urlPath.find("//") != string::npos) {
        strDomain = urlPath.substr(urlPath.find("//")+2);
        strDomainAndPort = strDomain;
        if(strDomain.find("/") != string::npos) {
            strDomain = strDomain.substr(0, strDomain.find("/"));
            strDomainAndPort = strDomain;
        }
        if(strDomain.find(":") != string::npos) {
            string strPort = strDomain.substr(strDomain.find(":")+1);
            strDomain = strDomain.substr(0, strDomain.find(":"));
            nPort = atoi(strPort.c_str());
        }    
        requestAddress = requestAddress.substr(strDomainAndPort.length());
    }
    
    ConnPoolManage* connPoolManage = (ConnPoolManage*)Application::g_connPoolManage;
    ConnPool* pool = connPoolManage->getConnPool(strDomain);
    if(pool == NULL) {
        return;
    }

    string strRequestParams;
    cJSON* pChild = params;
    do {
        if(pChild != NULL && pChild->string != NULL) {
            if(strcmp(pChild->string, "headers") != 0) {
                strRequestParams += (LINE_START + BOUNDARY + LINE_END);
                strRequestParams += "Content-Disposition:form-data;name=\"";
                strRequestParams += pChild->string;
                strRequestParams += "\"";
                strRequestParams += (LINE_END+LINE_END);
                strRequestParams += pChild->valuestring;
                strRequestParams += LINE_END;
            }
            pChild = pChild->child;    
        }
    } while(pChild != NULL && pChild->string != NULL);

    strRequestParams += (LINE_START + BOUNDARY + LINE_END);
    strRequestParams += "Content-Disposition:form-data;name=\"";
    strRequestParams += strFileKey;
    strRequestParams += "\";";
    strRequestParams += " filename=\"";
    strRequestParams += strFileName;
    strRequestParams += "\"";
    strRequestParams += LINE_END;
    strRequestParams += "Content-Type:";
    strRequestParams += strMimeType;
    strRequestParams += (LINE_END + LINE_END);
    
    string strTailParams = LINE_END+LINE_START+BOUNDARY+LINE_START+LINE_END;
    
    string strRequest;
    strRequest = httpMethod + " " + requestAddress + " HTTP/1.1\r\n"; //%s %s HTTP/1.1\r\n
    
    vector<SMemPage> vecMemBuf;
    ((CMemPool*)Application::g_memPool)->MallocPage(vecMemBuf, 1);
    if(vecMemBuf.size() < 1) {
        OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "FileTransfer", "((CMemPool*)Application::g_memPool)->MallocPage(vecMemBuf, 1) == NULL");
        return;
    }
    
    char* szBuf = vecMemBuf[0].m_point;
    if(nPort == 80 || nPort == 443)
        sprintf(szBuf, "Host:%s\r\n", strDomain.c_str());
    else
        sprintf(szBuf, "Host:%s:%d\r\n", strDomain.c_str(), nPort);
    strRequest += szBuf;
    
    sprintf(szBuf, "Connection:Keep-Alive\r\n");
    strRequest += szBuf;
    
    sprintf(szBuf, "Keep-Alive:timeout=5, max=1000\r\n");
    strRequest += szBuf;
    
    sprintf(szBuf, "Content-Length:%lu\r\n", nFileSize+strRequestParams.size()+strTailParams.size());
    strRequest += szBuf;
    
    if(headers != NULL) {
        int nCount = cJSON_GetArraySize(headers);
        for(int i=0; i<nCount; i++) {
            cJSON* pJson = cJSON_GetArrayItem(headers, i);
            if(pJson != nullptr) {
                if(pJson->type == cJSON_String) {
                    sprintf(szBuf, "%s:%s\r\n", pJson->string, pJson->valuestring);
                }
                if(pJson->type == cJSON_Number) {
                    sprintf(szBuf, "%s:%f\r\n", pJson->string, pJson->valuedouble);
                }
                strRequest += szBuf;
            }
        }
    }
    
    string strHttpUrl = isHttps?"https://"+strDomainAndPort:"http://"+strDomainAndPort;
    if(Application::g_cookieManage != NULL && !ARKWEB_MEMBER_MISSING(Application::g_cookieManage, existCookies)) {
        if(Application::g_cookieManage->existCookies(false)) {
            if(!ARKWEB_MEMBER_MISSING(Application::g_cookieManage, fetchCookieSync)) {
                char* pCookieValue = NULL;
                Application::g_cookieManage->fetchCookieSync(strHttpUrl.c_str(), false, true, &pCookieValue);
                if(pCookieValue != NULL && strlen(pCookieValue) > 0) {
                    string strCookies = pCookieValue;
                    string strCookie = "Set-Cookie:";
                    size_t pos;
                    while ((pos = strCookies.find(strCookie)) != std::string::npos) {
                        strCookies.erase(pos, strCookie.length());
                    }
                    sprintf(szBuf, "Cookie:%s\r\n", strCookies.c_str());
                    strRequest += szBuf;
                }
                if(pCookieValue != NULL) {
                    OH_ArkWeb_ReleaseString(pCookieValue);
                }    
            }
        }
    }
    
    sprintf(szBuf, "Content-Type: multipart/form-data; boundary=%s\r\n\r\n", BOUNDARY.c_str());
    strRequest += szBuf;
    ((CMemPool*)Application::g_memPool)->FreePage(vecMemBuf);
    
    strRequest += strRequestParams;
    
    int nBytesSent = 0;
    vector<SMemPage>  vecMemPage;
    if(isHttps) {
        bool isClose = true;
        SSL* ssl = NULL;
        if(!pool->getSSL(&ssl, nPort)) {
            OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "FileTransfer", "pool->getSocket(&ssl) == false");
        }else if(!pool->uploadFileWithTimeOut(ssl, strRequest, strTailParams, strSource, pBuf, nLength, std::ref(pRequest->getAbort()), &cbc) && !pRequest->getAbort()) {
            OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN,"FileTransfer","pool->sendWithTimeOut(ssl, strRequest) == false");
        }else if(!pRequest->getAbort() && !pool->recvHttpWithTimeOut(ssl,  vecMemPage, pBuf, nLength, isClose, std::ref(pRequest->getAbort()))) {
            ((CMemPool*)Application::g_memPool)->FreePage(vecMemPage);
            OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "FileTransfer","pool->recvHttpWithTimeOut(ssl, requestAddress, pMaxBuffer, nBufSize, isReconnect) == false");
        }
        pool->freeSocket(ssl, true);
    } else {
        bool isClose = false;
        int nSocket = -1;
        if(!pool->getSocket(nSocket,nPort)) {
            OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "FileTransfer",  "pool->getSocket(nSocket) == false");
        }else if(!pRequest->getAbort() && !pool->uploadFileWithTimeOut(nSocket, strRequest,strTailParams,  strSource, pBuf, nLength,std::ref(pRequest->getAbort()), &cbc)&& !pRequest->getAbort()) {
            OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "FileTransfer",  "pool->sendWithTimeOut(nSocket, strRequest) == false");
        }else if(!pool->recvHttpWithTimeOut(nSocket, vecMemPage, pBuf, nLength, isClose, std::ref(pRequest->getAbort()))) {
            OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "FileTransfer", "pool->recvHttpWithTimeOut(nSocket, requestAddress, pMaxBuffer, nBufSize, isReconnect) == false");
           
        }
        pool->freeSocket(nSocket, true);
    }
    
    if(vecMemPage.empty() && !pRequest->getAbort()) {
        cJSON* error = createFileTransferError(CONNECTION_ERR, strSource, strTarget, "", 0, "");
        cbc.error(error);
        cJSON_Delete(error);
        return;
    }
    
    if(pRequest->getAbort()) {
        cJSON* error = createFileTransferError(ABORTED_ERR, strSource, strTarget, "User canceled", 0, "User canceled");
        cbc.error(error);
        cJSON_Delete(error);
        return;
    }
    char* pResponse = vecMemPage[0].m_point;
    int nResponseSize = vecMemPage[0].m_nCount;
    
    char szResponseBuf[nResponseSize+1];
    memset(szResponseBuf, 0, sizeof(szResponseBuf));
    memcpy(szResponseBuf, pResponse, nResponseSize);
    CMemPool* pMemPool = (CMemPool*)Application::g_memPool;
    pMemPool->FreePage(vecMemPage);
    
    int nResponseCode = pool->getHttpCode(pResponse, nResponseSize);
    if(nResponseCode != 200) {
        cJSON* error = createFileTransferError(CONNECTION_ERR, strSource, strTarget, "", 0, "");
        cbc.error(error);
        cJSON_Delete(error);
        return;
    }
    
    string strResponse = &szResponseBuf[pool->getHttpHeader(pResponse, nResponseSize)];
    strResponse = strResponse.erase(0, strResponse.find_first_not_of(" "));
    strResponse = strResponse.erase(strResponse.find_last_not_of(" ") + 1);
    
    FileUploadResult result;
    result.m_nByteSent = nBytesSent;
    result.m_nResponseCode = nResponseCode;
    result.m_strResponse = strResponse;
    result.m_strObjectId = objectId;
    cJSON* pJson = createFileTransferResult(result);
    cbc.success(pJson);
    cJSON_Delete(pJson);
    return;
}

string FileTransfer::getArgument(cJSON* args, int position, string defaultString)
{
    string arg = defaultString;
    if(cJSON_GetArraySize(args) > position) {
        if(cJSON_GetArrayItem(args, position)->type == cJSON_String) {
            char* pArg = cJSON_GetArrayItem(args, position)->valuestring;
            if(pArg == NULL || strcmp(pArg, "null")==0) {
                arg = defaultString;
            } else {
                arg = pArg;
            }
        }
        if(cJSON_GetArrayItem(args, position)->type == cJSON_Number) {
            int nNumber = cJSON_GetArrayItem(args, position)->valueint;
            char szBuf[64];
            sprintf(szBuf, "%d", nNumber);
            arg = szBuf;
        }
    }
    return arg;
}
void FileTransfer::download(const string& strSource, const string& strTarget, cJSON* args, void* pBuf, const int nLength,  CallbackContext cbc, HttpRequest* pRequest)
{
    string objectId = getArgument(args, 3, ""); 
    
    cJSON* headers = NULL;
    if(cJSON_GetArrayItem(args, 4) == NULL) {
        headers = cJSON_GetObjectItem(args, "headers");
    } else {
        headers = cJSON_GetArrayItem(args, 4);
    }
    
    pRequest->setReqId(objectId);
    setHttpRequestThread(pRequest);
    
    //1，解析url
    string urlPath = strSource;
    string requestAddress = "";
    urlPath = urlPath.erase(0, urlPath.find_first_not_of(" "));
    urlPath = urlPath.erase(urlPath.find_last_not_of(" ") + 1);
    if(urlPath.find("//") != string::npos) {
        requestAddress = urlPath.substr(urlPath.find("//")+2);
    }
    
    //2,解析http/https协议类型
    int nPort = 0;
    bool isHttps = false;
    if(urlPath.find("https") == 0) {
        isHttps = true;
        nPort = 443;
    } else if(urlPath.find("http") == 0) {
        isHttps = false;
        nPort = 80;
    } else {
        return;
    }
    
    //3解析域名修改请求地址
    string strDomainAndPort;
    string strDomain;
    if(urlPath.find("//") != string::npos) {
        strDomain = urlPath.substr(urlPath.find("//")+2);
        strDomainAndPort = strDomain;
        if(strDomain.find("/") != string::npos) {
            strDomain = strDomain.substr(0, strDomain.find("/"));
            strDomainAndPort = strDomain;
        }
        if(strDomain.find(":") != string::npos) {
            string strPort = strDomain.substr(strDomain.find(":")+1);
            strDomain = strDomain.substr(0, strDomain.find(":"));
            nPort = atoi(strPort.c_str());
        }    
        requestAddress = requestAddress.substr(strDomainAndPort.length());
    }
    
    
    string strRequest;
    strRequest = "GET " + requestAddress + " HTTP/1.1\r\n"; //GET %s HTTP/1.1\r\n
    
    vector<SMemPage> vecMemBuf;
    ((CMemPool*)Application::g_memPool)->MallocPage(vecMemBuf, 1);
    if(vecMemBuf.size() < 1) {
        OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "FileTransfer", "((CMemPool*)Application::g_memPool)->MallocPage(vecMemBuf, 1) == NULL");
        return;
    }
    
    char* szBuf = vecMemBuf[0].m_point;
    if(nPort == 80 || nPort == 443)
        sprintf(szBuf, "Host:%s\r\n", strDomain.c_str());
    else
        sprintf(szBuf, "Host:%s:%d\r\n", strDomain.c_str(), nPort);
    strRequest += szBuf;
    
    sprintf(szBuf, "Connection:Keep-Alive\r\n");
    strRequest += szBuf;
    
    if(headers != NULL) {
        int nCount = cJSON_GetArraySize(headers);
        for(int i=0; i<nCount; i++) {
            cJSON* pJson = cJSON_GetArrayItem(headers, i);
            if(pJson != nullptr) {
                if(pJson->type == cJSON_String) {
                    sprintf(szBuf, "%s:%s\r\n", pJson->string, pJson->valuestring);
                }
                if(pJson->type == cJSON_Number) {
                    sprintf(szBuf, "%s:%f\r\n", pJson->string, pJson->valuedouble);
                }
                strRequest += szBuf;
            }
        }
    }
    
    string strHttpUrl = isHttps?"https://"+strDomainAndPort:"http://"+strDomainAndPort;
    if(Application::g_cookieManage != NULL && !ARKWEB_MEMBER_MISSING(Application::g_cookieManage, existCookies)) {
        if(Application::g_cookieManage->existCookies(false)) {
            if(!ARKWEB_MEMBER_MISSING(Application::g_cookieManage, fetchCookieSync)) {
                char* pCookieValue = NULL;
                Application::g_cookieManage->fetchCookieSync(strHttpUrl.c_str(), false, true, &pCookieValue);
                if(pCookieValue != NULL && strlen(pCookieValue) > 0) {
                    string strCookies = pCookieValue;
                    string strCookie = "Set-Cookie:";
                    size_t pos;
                    while ((pos = strCookies.find(strCookie)) != std::string::npos) {
                        strCookies.erase(pos, strCookie.length());
                    }
                    sprintf(szBuf, "Cookie:%s\r\n", strCookies.c_str());
                    strRequest += szBuf;
                }
                if(pCookieValue != NULL) {
                    OH_ArkWeb_ReleaseString(pCookieValue);
                }    
            }
        }
    }
    
    sprintf(szBuf, "Keep-Alive:timeout=5, max=1000\r\n\r\n");
    strRequest += szBuf;
    ((CMemPool*)Application::g_memPool)->FreePage(vecMemBuf);
    
    ConnPoolManage* connPoolManage = (ConnPoolManage*)Application::g_connPoolManage;
    ConnPool* pool = connPoolManage->getConnPool(strDomain);
    if(pool == NULL) {
        return;
    }
    
    string strFileName = strTarget;
    map<string, string>  mapRespHeaders;
    if(isHttps) {
        bool isClose = false;
        SSL* ssl = NULL;
        if(!pool->getSSL(&ssl, nPort)) {
            OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "FileTransfer", "pool->getSocket(&ssl) == false");
        }else if(!pool->sendWithTimeOut(ssl, strRequest, std::ref(pRequest->getAbort()))) {
            OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "FileTransfer", "pool->sendWithTimeOut(ssl, strRequest) == false");
        }else if(!pool->recvHttpWithTimeOut(ssl, strFileName, mapRespHeaders, "", pBuf, nLength, isClose, std::ref(pRequest->getAbort()), &cbc)) {
            OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "FileTransfer", "pool->recvHttpWithTimeOut(ssl, strFileName, pMaxBuffer, nBufSize, isReconnect) == false");
        }
        pool->freeSocket(ssl, isClose);
    } else {
        bool isClose = false;
        int nSocket = -1;
        if(!pool->getSocket(nSocket, nPort)) {
            OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "FileTransfer", "pool->getSocket(nSocket) == false");
        }else if(!pool->sendWithTimeOut(nSocket, strRequest, std::ref(pRequest->getAbort()))) {
            OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "FileTransfer", "pool->sendWithTimeOut(nSocket, strRequest) == false");
        }else if(!pool->recvHttpWithTimeOut(nSocket, strFileName, mapRespHeaders, "", pBuf, nLength, isClose, std::ref(pRequest->getAbort()), &cbc)) {
            OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "FileTransfer", "pool->recvHttpWithTimeOut(nSocket, strFileName, pMaxBuffer, nBufSize, isReconnect) == false");
        }
        pool->freeSocket(nSocket, true);
    }
    
    if(pRequest->getAbort()) {
        cJSON* error = createFileTransferError(ABORTED_ERR, strSource, strTarget, "User canceled", 0, "User canceled");
        cbc.error(error);
        cJSON_Delete(error);
        return;
    }
    if(!FileCache::IsFile(strFileName, "")) {
        cJSON* error = createFileTransferError(CONNECTION_ERR, strSource, strTarget, "", 0, "");
        cbc.error(error);
        cJSON_Delete(error);
        return;
    }
    
    cJSON* pJson = FileUtils::makeEntryForUrl(strFileName);
    cbc.success(pJson);
    cJSON_Delete(pJson);
    return;
}

cJSON* FileTransfer::createFileTransferError(int errorCode, string source, string target, string body, int httpStatus, string msg)
{
    cJSON* error = cJSON_CreateObject();
    cJSON_AddNumberToObject(error, "code", errorCode);
    cJSON_AddStringToObject(error, "source", source.c_str());
    cJSON_AddStringToObject(error, "target", target.c_str());
    if(!body.empty()) {
        cJSON_AddStringToObject(error, "body", body.c_str());
    }
    cJSON_AddNumberToObject(error, "http_status", httpStatus);
    cJSON_AddStringToObject(error, "exception", msg.c_str());
    return error;
}

cJSON* FileTransfer::createFileTransferResult(FileTransfer::FileUploadResult result)
{
    cJSON* json = cJSON_CreateObject();
    cJSON_AddNumberToObject(json, "bytesSent", result.m_nByteSent);
    cJSON_AddNumberToObject(json, "responseCode", result.m_nResponseCode);
    cJSON_AddStringToObject(json, "response", result.m_strResponse.c_str());
    cJSON_AddStringToObject(json, "objectId", result.m_strObjectId.c_str());
    return json;
}

void FileTransfer::HttpRequest::Execute(void* arg)
{
    string strSource = cJSON_GetArrayItem(m_pArgs, 0)->valuestring;
    string strTarget = cJSON_GetArrayItem(m_pArgs, 1)->valuestring;
    void* pBuf = InitThreadData();
    if(m_strMethod == "upload") {
        m_fileTransfer->upload(strSource, strTarget, m_pArgs, pBuf, m_nTempBufSize, m_cbc,this);
    } else {
        m_fileTransfer->download(strSource, strTarget, m_pArgs,pBuf, m_nTempBufSize, m_cbc,this);
    }
    DeInitThreadData(pBuf);
    cJSON_Delete(m_pArgs);
}

void* FileTransfer::HttpRequest::InitThreadData()
{
    vector<SMemPage> vecMemBuf;
    ((CMemPool*)Application::g_memPool)->MallocPage(vecMemBuf, 1);
    if(vecMemBuf.size() < 1) {
        OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "FileTransfer", "((CMemPool*)Application::g_memPool)->MallocPage(vecMemBuf, 1) == NULL");
        return NULL;
    }
    m_nTempBufSize = ((CMemPool*)Application::g_memPool)->GetPageSize();
    return vecMemBuf[0].m_point;
}
void FileTransfer::HttpRequest::DeInitThreadData(void* pArg)
{
    ((CMemPool*)Application::g_memPool)->FreePage((char*)pArg);
}